package com.acme.bankapp.service.app;

import java.util.Collection;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.acme.bankapp.domain.bank.Bank;
import com.acme.bankapp.domain.bank.Client;
import com.acme.bankapp.domain.bank.exceptions.ClientExistsException;

public class BankService {
	EventDispatcher dispatcher;
	Bank bank;
	Executor eventExecutor;
	
	public BankService(Bank bank, EventDispatcher dispatcher, Executor eventExecutor) {
		this.bank = bank;
		this.dispatcher = dispatcher;
		if (eventExecutor != null) {
			this.eventExecutor = eventExecutor;
		} else {
			this.eventExecutor = new ThreadPoolExecutor(4, 16, 1l, TimeUnit.MINUTES,
					new MyLittleBlockingQueue<Runnable>());
		}
	}
	
	public boolean hasClientWithName(String name) {
		for (Client c : bank.getClients()) {
			if (c.getName().equals(name)) {
				return true;
			}
		}
		return false;
	}
	
	public Collection<Client> getClients() {
		return bank.getClients();
	}
	
	public void addClient(Client client) throws ClientExistsException {
		if (hasClientWithName(client.getName())) {
			throw new ClientExistsException();
		}
		bank.addClient(client);
	}
	
	public void addHandler(Class<? extends BankEvent> eventType, EventHandler handler) {
		dispatcher.addHandler(eventType, handler);
	}
	
	public void raiseEvent(final BankEvent event) {
		eventExecutor.execute(new Runnable(){
			@Override
			public void run() {
				dispatcher.dispatch(event);
			}
		});
	}
}
